/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.core.editpart;

import org.eclipse.draw2d.geometry.Point;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.requests.CreateConnectionRequest;
import org.eclipse.gef.requests.ReconnectRequest;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PlatformUI;

import com.cea.papyrus.core.commands.connection.ConnectionCreateCommand;
import com.cea.papyrus.core.commands.connection.ConnectionReconnectCommand;
import com.cea.papyrus.core.editor.DiagramEditorPage;
import com.cea.papyrus.core.editor.MultiDiagramEditor;
import com.cea.papyrus.core.editor.abstracteditor.AbstractGraphicalPageWithFlyoutPalette;
import com.cea.papyrus.core.editpart.connection.ConnectionsEditPolicy;
import com.cea.papyrus.core.helper.ModelerHelper;
import com.cea.papyrus.core.pseudoelement.EnhancedType;
import com.cea.papyrus.core.pseudoelement.UMLElementFactory;
import com.cea.papyrus.diagraminterchange2.di2.Diagram;
import com.cea.papyrus.diagraminterchange2.di2.GraphEdge;
import com.cea.papyrus.diagraminterchange2.di2.GraphElement;
import com.cea.papyrus.diagraminterchange2.di2.Uml1SemanticModelBridge;

/**
 * EditPolicy for connections on Edge.
 * Most of the methods are common with GraphNodeEditPolicy. Should have a common ancestor.
 * 
 * @author dumoulin
 */
public class EdgeConnectionsEditPolicy extends ConnectionsEditPolicy {
	
	/**
	 * Is the handler allowed ?.
	 * 
	 * @return 
	 */
	protected boolean isAllowed()
	{
		return (getHost().getModel() instanceof GraphEdge);
	}
	
	/* 
	 * End creation of the connection. The previous command is retrieved
	 * and the target is set.
	 */
	/**
	 * 
	 * 
	 * @param request 
	 * 
	 * @return 
	 */
	@Override
	protected Command getConnectionCompleteCommand(CreateConnectionRequest request) {
		ConnectionCreateCommand cmd 
		= (ConnectionCreateCommand) request.getStartCommand();

		if (!(isAllowed())) {
			return cmd;
		}

		//Darpan
		//TODO:
		Diagram diagram = null;
		IEditorPart editorPart = PlatformUI
				.getWorkbench()
				.getActiveWorkbenchWindow()
				.getActivePage()
				.getActiveEditor();
		if (editorPart instanceof MultiDiagramEditor) {
			MultiDiagramEditor mde = (MultiDiagramEditor) editorPart;
			DiagramEditorPage cde=(DiagramEditorPage)mde.getActiveEditor();
			diagram = cde.getDiagramModel();
		} else if (editorPart instanceof AbstractGraphicalPageWithFlyoutPalette) {
			diagram = ((AbstractGraphicalPageWithFlyoutPalette) editorPart).getDiagramModel();
		}
		cmd.setParent(diagram);
		Point location = computeAnchorLocation(request.getLocation(), getHost());
		cmd.setTarget((GraphElement) getHost().getModel(), location);
		return cmd;
	}

	/* 
	 * Start creation of a connection. The Command is created, and the src is set.
	 */
	/**
	 * 
	 * 
	 * @param request 
	 * 
	 * @return 
	 */
	@Override
	protected Command getConnectionCreateCommand(CreateConnectionRequest request) {

		Class type;
		Object newObjectDescription 
		= EnhancedType.getNewObjectDescription(request);

		if (!isAllowed()) {
			return null;
		}

		GraphElement source        = (GraphElement) getHost().getModel();
		GraphElement container  = source.getContainer();

		// Test creation restriction in Connector creation
		// (due to filters defined in PaletteMenu extension
		boolean noRestriction = true;
		if (newObjectDescription instanceof UMLElementFactory) {
			UMLElementFactory enhancedType = (UMLElementFactory) newObjectDescription;
			type          = enhancedType.getClazz();
			noRestriction = enhancedType.canExecute(source);
		} else {
			type = (Class)  newObjectDescription;
		}

//		if((!(container instanceof Diagram))
//				&&	(container.getSemanticModel() == null)) {
//			// the source dont have to be a property for instance.
//			return null; 
//		}

		Point location = computeAnchorLocation(request.getLocation(), getHost());
		
		if(((Uml1SemanticModelBridge)source.getSemanticModel())!=null&&
				ModelerHelper.getFactory().canConnect(type, ((Uml1SemanticModelBridge)source.getSemanticModel()).getElement(),null) && noRestriction) {
			ConnectionCreateCommand cmd = new ConnectionCreateCommand(source, newObjectDescription, location);
			request.setStartCommand(cmd);
			return cmd;
		}
		return null;
	}


/* 
 * Returns the <code>Command</code> to reconnect a connection's <i>source</i> end to the
 * host.
 */
/**
 * 
 * 
 * @param request 
 * 
 * @return 
 */
@Override
protected Command getReconnectSourceCommand(ReconnectRequest request) {
	if (!(isAllowed())) {
		return null;
	}

	GraphEdge connector = (GraphEdge) request.getConnectionEditPart().getModel();
	GraphElement newSource = (GraphElement) getHost().getModel();

	Point location = computeAnchorLocation(request.getLocation(), getHost());
	ConnectionReconnectCommand cmd = new ConnectionReconnectCommand(connector, newSource, location, ConnectionReconnectCommand.SOURCE);
	return cmd;
}
/* 
 * Returns the <code>Command</code> to reconnect a connection's <i>target</i> end to the
 * host.
 */
/**
 * 
 * 
 * @param request 
 * 
 * @return 
 */
@Override
protected Command getReconnectTargetCommand(ReconnectRequest request) {
	if (!(isAllowed())) {
		return null;
	}

	GraphEdge connector = (GraphEdge) request.getConnectionEditPart().getModel();
	GraphElement newTarget = (GraphElement) getHost().getModel();

	Point location = computeAnchorLocation(request.getLocation(), getHost());
	ConnectionReconnectCommand cmd = new ConnectionReconnectCommand(connector, newTarget, location, ConnectionReconnectCommand.TARGET);
	return cmd;
}
}
